#include <cstdlib>
#include <iostream>
#include "CsbufParser.h"
#include "test/test_csbuf.h"

template <typename T>
bool isEqual(const T &x, const T &y)
{
	if (x != y)
		std::cout << x << " no equal " << y << std::endl;
	return false;
}

void testInt32(int32_t d) 
{
	CsbufParser p;
	p.setInt32(d, 1);
	// T.Log(p.GetData())
	auto dd = p.getInt32(1);
	if (dd != d) {
		std::cout << "SetInt32 and GetInt32 no error" << d << dd << std::endl;
	}
}

void testUint32(uint32_t d) {
	CsbufParser p;
	p.setUint32(d, 1);
	//T.Log(p.GetData())
	auto dd = p.getUint32(1);
	if (dd != d) {
		std::cout << "SetUint32 and GetUint32 no error" << d << dd << std::endl;
	}
}

int main()
{
	CsbufParser parser;

	uint8_t a = 2;
	uint16_t b = 6000;
	uint32_t c = 123456789;
	uint64_t d = 123456789123;
	float e = 1.11f;
	std::string f("just test!");

	int8_t aa = -2;
	int16_t bb = -6000;
	int32_t cc = -123456789;
	int64_t dd = -123456789123;

	bool g = true;
	double h = 2.223;

	parser.setUint8(a, 1);
	parser.setUint16(b, 2);
	parser.setUint32(c, 3);
	parser.setUint64(d, 4);
	parser.setFloat(e, 5);
	parser.setString(f.c_str(), 6);
	parser.setInt8(aa, 7);
	parser.setInt16(bb, 8);
	parser.setInt32(cc, 9);
	parser.setInt64(dd, 10);
	parser.setBool(g, 11);
	parser.setDouble(h, 12);

	CsbufParser p2;
	p2.setData(parser.getData().c_str(), parser.getData().size());
	isEqual<uint8_t>(p2.getUint8(1), a);
	isEqual<uint16_t>(p2.getUint16(2), b);
	isEqual<uint32_t>(p2.getUint32(3), c);
	isEqual<uint64_t>(p2.getUint64(4), d);
	isEqual<float>(p2.getFloat(5), e);
	isEqual<std::string>(p2.getString(6), f);
	isEqual<int8_t>(p2.getInt8(7), aa);
	isEqual<int16_t>(p2.getInt16(8), bb);
	isEqual<int32_t>(p2.getInt32(9), cc);
	isEqual<int64_t>(p2.getInt64(10), dd);
	isEqual<bool>(p2.getBool(11), g);
	isEqual<double>(p2.getDouble(12), h);
	std::cout << "test end" << std::endl;
// 	std::cout << (int)p2.getUint8(1) << std::endl;
// 	std::cout << p2.getUint16(2) << std::endl;
// 	std::cout << p2.getUint32(3) << std::endl;
// 	std::cout << p2.getUint64(4) << std::endl;
// 	std::cout << p2.getFloat(5) << std::endl;
// 	std::cout << p2.getString(6) << std::endl;
// 	std::cout << (int)p2.getInt8(7) << std::endl;
// 	std::cout << p2.getInt16(8) << std::endl;
// 	std::cout << p2.getInt32(9) << std::endl;
// 	std::cout << p2.getInt64(10) << std::endl;
// 	std::cout << p2.getBool(11) << std::endl;

	test::Test1 t1;
	t1.a_t1 = 1;
	t1.at_2 = 2;
	t1.at3_ = "struct test";
	t1.t4.push_back(1);
	t1.t4.push_back(2);
	t1.t5.push_back("c++");
	t1.t5.push_back("test");
// 	t1.t6.a = 100;
// 	t1.t6.b = "link test";

	test::Head m1;
// 	m1.a = 2;
// 	m1.b = "m1";
	t1.t7.push_back(m1);
	m1.a = 4;
	m1.b = "m2";
	t1.t7.push_back(m1);

	parser.clear();
	t1.Marshal(parser);

	test::Test2 t2;
	p2.clear();
	p2.setData(parser.getData().c_str(), parser.getData().size());
	t2.Unmarshal(p2);

	isEqual<uint8_t>(t1.a_t1, t2.a_t1);
	isEqual<uint32_t>(t1.at_2, t2.at_2);
	isEqual<std::string>(t1.at3_, t2.at3_);
// 	isEqual<uint32_t>(t1.t4[0], t2.t4[0]);
// 	isEqual<uint32_t>(t1.t4[1], t2.t4[1]);
// 	isEqual<std::string>(t1.t5[0], t2.t5[0]);
// 	isEqual<std::string>(t1.t5[1], t2.t5[1]);
	isEqual<uint32_t>(t1.t6.a, t2.t6.a);
	isEqual<std::string>(t1.t6.b, t2.t6.b);
	isEqual<uint32_t>(t1.t7[0].a, t2.t7[0].a);
	isEqual<std::string>(t1.t7[0].b, t2.t7[0].b);
	isEqual<uint32_t>(t1.t7[1].a, t2.t7[1].a);
	isEqual<std::string>(t1.t7[1].b, t2.t7[1].b);

	
	testInt32(-1);
	testInt32(-127);
	testInt32(-128);
	testInt32(127);
	testInt32(128);
	testInt32(-32768);
	testInt32(32767);
	testInt32(-32769);
	testInt32(32768);

	testUint32(1);
	testUint32(255);
	testUint32(256);
	testUint32(257);
	testUint32(128);
	testUint32(32768);
	testUint32(65535);
	testUint32(65536);
	testUint32(65537);

	std::getchar();
	return 0;
}